﻿#define _CRT_SECURE_NO_WARNINGS 1

#include<stdio.h>
#include<iostream>
using namespace std;

//int main()
//{
//	int a = 10;
//	int& b = a;
//	//引用必须初始化
//	//int& c;
//	int& d = b;
//	
//	cout << &a << endl;
//	cout << &b << endl;
//	cout << &d << endl;
//
//	int e = 20;
//	//这里并非让d引用e，因为C++引用不能改变指向
//	//所以这里是一个赋值
//	d = e;
//	cout << &a << endl;
//	cout << &b << endl;
//	cout << &d << endl;
//	cout << &e << endl;
//
//	return 0;
//}




//void Swap(int& x, int& y)
//{
//	int tmp = x;
//	x = y;
//	y = tmp;
//}
//
//int main()
//{
//	int a = 10;
//	int b = 13;
//	cout << a << ' ' << b << endl;
//	Swap(a, b);
//	cout << a << ' ' << b << endl;
//
//	return 0;
//}




//#include<assert.h>
//typedef int STDataType;
//typedef struct Stack
//{
//	STDataType* arr;
//	int top;
//	int capacity;
//}ST;
//
//void STInit(ST& rs, int n = 4)
//{
//	rs.arr = (STDataType*)malloc(n * sizeof(STDataType));
//	rs.top = 0;
//	rs.capacity = n;
//}
//
//// 栈顶
//void STPush(ST& rs, STDataType x)
//{
//	// 满了， 扩容
//	if (rs.top == rs.capacity)
//	{
//		printf("扩容\n");
//		int newcapacity = rs.capacity == 0 ? 4 : rs.capacity * 2;
//		STDataType* tmp = (STDataType*)realloc(rs.arr, newcapacity * sizeof(STDataType));
//		if (tmp == NULL)
//		{
//			perror("realloc fail!");
//			exit(1);
//		}
//		rs.arr = tmp;
//		rs.capacity = newcapacity;
//	}
//	rs.arr[rs.top] = x;
//	rs.top++;
//}

//程序会报错，因为左值不可被修改
//int STTop(ST& rs)
//{
//	assert(rs.top > 0);
//
//	//return &(rs.a[rs.top - 1]);
//	return rs.arr + (rs.top - 1);
//}
//int* STTop(ST& rs)
//{
//	assert(rs.top > 0);
//
//	//return &(rs.a[rs.top - 1]);
//	return rs.arr + (rs.top - 1);
//}
//int& STTop(ST& rs)
//{
//	assert(rs.top > 0);
//
//	return rs.arr[rs.top - 1];
//}

//同样程序会报错，因为左值不可被修改
//int func()
//{
//	int ret = 10;
//	ret++;
//	//...
//
//	return ret;
//}
//int& func()
//{
//	int ret = 10;
//	ret++;
//	//...
//
//	return ret;
//}
//
//int main()
//{
//	ST st1;
//	STInit(st1);
//	STPush(st1, 1);
//	STPush(st1, 2);
//	cout << STTop(st1) << endl;
//
//	// 修改栈顶的数据呢
//	(STTop(st1)) += 1;
//	cout << STTop(st1) << endl;
//
//	func() += 1;
//	//int ret = func() += 1;
//	//cout << ret << endl;
//
//	return 0;
//}




//int main()
//{
//	//越界不一定会报错
//	int arr[10];
//
//	//越界读不报错
//	cout << arr[10] << endl;
//	cout << arr[13] << endl;
//	cout << arr[16] << endl;
//	
//	//越界写不一定报错，vs一般是抽查
//	arr[10] = 1;
//	arr[13] = 1;
//	arr[16] = 1;
//	arr[20] = 1;
//
//	//在vs中，一般采用抽查模式
//	//一般会在数组末尾附近设置几个抽查位置，并一个赋值
//	//程序结束时看一下这几个值有没有被修改，修改了一定越界
//
//	return 0;
//}




//int main()
//{
//	const int a = 1;
//
//	//权项不能被放大
//	//int& ra = a;
//	const int& ra = a;
//	
//	int b = 3;
//	//权限可以被缩小
//	const int& rb = b;
//	//不可以给常量赋值
//	//rb++;
//
//	//这不是权限放大，是拷贝赋值
//	const int x = 13;
//	int y = x;
//
//	return 0;
//}




//int main()
//{
//	// 权限不能放大
//	const int a = 10;
//	const int* p1 = &a;
//	//int* p2 = p1;
//
//	// 权限可以缩小
//	int b = 20;
//	int* p3 = &b;
//	const int* p4 = p3;
//
//	// 不存在权限放大，因为const修饰的是p5本身不是指向的内容
//	int* const p5 = &b;
//	int* p6 = p5;
//
//	return 0;
//}




//void func(const T& rx)
//void func(const int& rx)
//{
//	cout << rx << endl;
//}
//
//int main()
//{
//	//就记住一点，C++规定的临时对象具有常行
//	//所以需要常引用
//	const int a = 10;
//
//	int b = 20;
//	const int& rb = b * 3;
//
//	double d = 12.34;
//	const int& rd = d;
//
//	func(a);
//	func(b);
//	func(b*3);
//	func(d);
//
//	return 0;
//}




//int main()
//{
//	char c = 'a';
//	char& rc = c;
//	cout << sizeof(rc) << endl;
//	char* ptr = &c;
//	cout << sizeof(ptr) << endl;
//
//	return 0;
//}




//int main()
//{
//	int x = 0;
//	int& rx = x;
//	rx += 1;
//
//	int* ptr = &x;
//	*ptr += 1;
//
//	return 0;
//}





// 实现一个ADD宏函数的常见问题
//#define ADD(int a, int b) return a + b;
//#define ADD(a, b) a + b;
//#define ADD(a, b) (a + b)

// 正确的宏实现
//#define ADD(a, b) ((a) + (b));
//#define ADD(a, b) (a) + (b)
//#define ADD(a, b) (a + b)
//#define ADD(a, b) ((a) + (b))

//#define ADD(a, b) ((a) + (b))
// 为什么不能加分号?
// 为什么要加外面的括号?
// 为什么要加里面的括号?
// 宏函数坑很多，但是替换机制，调用时不用建立栈帧，提效

//int main()
//{
//	int ret = ADD(1, 2); // int ret = ((1) + (2));;
//	cout << ret << endl;
//
//  //为什么不能加分号?
//	cout << ADD(1, 2) << endl;
// 
//	//为什么要加外面的括号?
//	cout << ADD(1, 2)*3 << endl;
//
//	//为什么要加里面的括号?
//	int x = 1, y = 2;
//	//ADD(x & y, x | y); // -> (x&y+x|y)
//
//	ADD(x & y, x | y); // -> ((x&y)+(x|y))
//
//	return 0;
//}

// inline没有宏函数的坑，也不用建立栈帧，提效
//不展开
//inline int Add(int x, int y)
//{
//	int ret = x + y;
//	ret += 1;
//	ret += 1;
//	ret += 1;
//	ret += 1;
//	ret += 1;
//	ret += 1;
//	ret += 1;
//	ret += 1;
//	ret += 1;
//	ret += 1;
//
//	return ret;
//}

////展开
//inline int Add(int x, int y)
//{
//	int ret = x + y;
//	ret += 1;
//
//	return ret;
//}
//
//int main()
//{
//	//可以通过汇编观察程序是否展开
//	//有call Add语句就是没有展开，没有就是展开了
//	int rr = Add(1, 2);
//	cout << rr << endl;
//
//	//要强调的一个点是
//	//函数编译以后是一堆指令，需要存储起来执行
//	//第一句指令的地址就是函数的地址
//
//	return 0;
//}




//#include"Func.h"
//int main()
//{
//	// 链接错误：⽆法解析的外部符号 "void __cdecl f(int)" (?f@@YAXH@Z)
//	fun(1);
//
//	return 0;
//}




//void func(int x)
//{
//	cout << "func(int x)" << endl;
//}
//
//void func(int* ptr)
//{
//	cout << "func(int* ptr)" << endl;
//}
//
//int main()
//{
//	func(0);
//	func(NULL);
//	
//	func((int*)NULL);
//	//func((void*)0);
//	func(nullptr);
//
//	return 0;
//}
//